home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / OTHERCST / JPSRC_FO / JRDJFIF.C < prev    next >
Text File  |  1991-10-13  |  18KB  |  734 lines

  1. /*
  2.  * jrdjfif.c
  3.  *
  4.  * Copyright (C) 1991, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to decode standard JPEG file headers/markers.
  9.  * This will handle baseline and JFIF-convention JPEG files.
  10.  *
  11.  * This module relies on the JGETC macro and the read_jpeg_data method (which
  12.  * is provided by the user interface) to read from the JPEG data stream.
  13.  * Therefore, this module is NOT dependent on any particular assumption about
  14.  * the data source.  This fact does not carry over to more complex JPEG file
  15.  * formats such as JPEG-in-TIFF; those format control modules may well need to
  16.  * assume stdio input.
  17.  *
  18.  * read_file_header assumes that reading begins at the JPEG SOI marker
  19.  * (although it will skip non-FF bytes looking for a JPEG marker).
  20.  * The user interface must position the data stream appropriately.
  21.  *
  22.  * These routines are invoked via the methods read_file_header,
  23.  * read_scan_header, read_jpeg_data, read_scan_trailer, and read_file_trailer.
  24.  */
  25.  
  26. #include "jinclude.h"
  27.  
  28. #ifdef JFIF_SUPPORTED
  29.  
  30.  
  31. typedef enum {            /* JPEG marker codes */
  32.   M_SOF0  = 0xc0,
  33.   M_SOF1  = 0xc1,
  34.   M_SOF2  = 0xc2,
  35.   M_SOF3  = 0xc3,
  36.   
  37.   M_SOF5  = 0xc5,
  38.   M_SOF6  = 0xc6,
  39.   M_SOF7  = 0xc7,
  40.   
  41.   M_JPG   = 0xc8,
  42.   M_SOF9  = 0xc9,
  43.   M_SOF10 = 0xca,
  44.   M_SOF11 = 0xcb,
  45.   
  46.   M_SOF13 = 0xcd,
  47.   M_SOF14 = 0xce,
  48.   M_SOF15 = 0xcf,
  49.   
  50.   M_DHT   = 0xc4,
  51.   
  52.   M_DAC   = 0xcc,
  53.   
  54.   M_RST0  = 0xd0,
  55.   M_RST1  = 0xd1,
  56.   M_RST2  = 0xd2,
  57.   M_RST3  = 0xd3,
  58.   M_RST4  = 0xd4,
  59.   M_RST5  = 0xd5,
  60.   M_RST6  = 0xd6,
  61.   M_RST7  = 0xd7,
  62.   
  63.   M_SOI   = 0xd8,
  64.   M_EOI   = 0xd9,
  65.   M_SOS   = 0xda,
  66.   M_DQT   = 0xdb,
  67.   M_DNL   = 0xdc,
  68.   M_DRI   = 0xdd,
  69.   M_DHP   = 0xde,
  70.   M_EXP   = 0xdf,
  71.   
  72.   M_APP0  = 0xe0,
  73.   M_APP15 = 0xef,
  74.   
  75.   M_JPG0  = 0xf0,
  76.   M_JPG13 = 0xfd,
  77.   M_COM   = 0xfe,
  78.   
  79.   M_TEM   = 0x01,
  80.   
  81.   M_ERROR = 0x100
  82. } JPEG_MARKER;
  83.  
  84.  
  85. /*
  86.  * Reload the input buffer after it's been emptied, and return the next byte.
  87.  * This is exported for direct use by the entropy decoder.
  88.  * See the JGETC macro for calling conditions.
  89.  *
  90.  * For this header control module, read_jpeg_data is supplied by the
  91.  * user interface.  However, header formats that require random access
  92.  * to the input file would need to supply their own code.  This code is
  93.  * left here to indicate what is required.
  94.  */
  95.  
  96. #if 0                /* not needed in this module */
  97.  
  98. METHODDEF int
  99. read_jpeg_data (decompress_info_ptr cinfo)
  100. {
  101.   cinfo->bytes_in_buffer = fread(cinfo->input_buffer + MIN_UNGET,
  102.                  1, JPEG_BUF_SIZE,
  103.                  cinfo->input_file);
  104.   
  105.   cinfo->next_input_byte = cinfo->input_buffer + MIN_UNGET;
  106.   
  107.   if (cinfo->bytes_in_buffer <= 0)
  108.     ERREXIT(cinfo->emethods, "Unexpected EOF in JPEG file");
  109.  
  110.   return JGETC(cinfo);
  111. }
  112.  
  113. #endif
  114.  
  115.  
  116. /*
  117.  * Routines to parse JPEG markers & save away the useful info.
  118.  */
  119.  
  120.  
  121. LOCAL INT32
  122. get_2bytes (decompress_info_ptr cinfo)
  123. /* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
  124. {
  125.   INT32 a;
  126.   
  127.   a = JGETC(cinfo);
  128.   return (a << 8) + JGETC(cinfo);
  129. }
  130.  
  131.  
  132. LOCAL void
  133. skip_variable (decompress_info_ptr cinfo, int code)
  134. /* Skip over an unknown or uninteresting variable-length marker */
  135. {
  136.   INT32 length;
  137.   
  138.   length = get_2bytes(cinfo);
  139.   
  140.   TRACEMS2(cinfo->emethods, 1,
  141.        "Skipping marker 0x%02x, length %d", code, length);
  142.   
  143.   for (length -= 2; length > 0; length--)
  144.     (void) JGETC(cinfo);
  145. }
  146.  
  147.  
  148. LOCAL void
  149. get_dht (decompress_info_ptr cinfo)
  150. /* Process a DHT marker */
  151. {
  152.   INT32 length;
  153.   UINT8 bits[17];
  154.   UINT8 huffval[256];
  155.   int i, index, count;
  156.   HUFF_TBL **htblptr;
  157.   
  158.   length = get_2bytes(cinfo)-2;
  159.   
  160.   while (length > 0) {
  161.     index = JGETC(cinfo);
  162.  
  163.     TRACEMS1(cinfo->emethods, 1, "Define Huffman Table 0x%02x", index);
  164.       
  165.     bits[0] = 0;
  166.     count = 0;
  167.     for (i = 1; i <= 16; i++) {
  168.       bits[i] = JGETC(cinfo);
  169.       count += bits[i];
  170.     }
  171.  
  172.     TRACEMS8(cinfo->emethods, 2, "        %3d %3d %3d %3d %3d %3d %3d %3d",
  173.          bits[1], bits[2], bits[3], bits[4],
  174.          bits[5], bits[6], bits[7], bits[8]);
  175.     TRACEMS8(cinfo->emethods, 2, "        %3d %3d %3d %3d %3d %3d %3d %3d",
  176.          bits[9], bits[10], bits[11], bits[12],
  177.          bits[13], bits[14], bits[15], bits[16]);
  178.  
  179.     if (count > 256)
  180.       ERREXIT(cinfo->emethods, "Bogus DHT counts");
  181.  
  182.     for (i = 0; i < count; i++)
  183.       huffval[i] = JGETC(cinfo);
  184.  
  185.     length -= 1 + 16 + count;
  186.  
  187.     if (index & 0x10) {        /* AC table definition */
  188.       index -= 0x10;
  189.       htblptr = &cinfo->ac_huff_tbl_ptrs[index];
  190.     } else {            /* DC table definition */
  191.       htblptr = &cinfo->dc_huff_tbl_ptrs[index];
  192.     }
  193.  
  194.     if (index < 0 || index >= NUM_HUFF_TBLS)
  195.       ERREXIT1(cinfo->emethods, "Bogus DHT index %d", index);
  196.  
  197.     if (*htblptr == NULL)
  198.       *htblptr = (*cinfo->emethods->alloc_small) (SIZEOF(HUFF_TBL));
  199.   
  200.     memcpy((void *) (*htblptr)->bits, (void *) bits,
  201.        SIZEOF((*htblptr)->bits));
  202.     memcpy((void *) (*htblptr)->huffval, (void *) huffval,
  203.        SIZEOF((*htblptr)->huffval));
  204.     }
  205. }
  206.  
  207.  
  208. LOCAL void
  209. get_dac (decompress_info_ptr cinfo)
  210. /* Process a DAC marker */
  211. {
  212.   INT32 length;
  213.   int index, val;
  214.  
  215.   length = get_2bytes(cinfo)-2;
  216.   
  217.   while (length > 0) {
  218.     index = JGETC(cinfo);
  219.     val = JGETC(cinfo);
  220.  
  221.     TRACEMS2(cinfo->emethods, 1,
  222.          "Define Arithmetic Table 0x%02x: 0x%02x", index, val);
  223.  
  224.     if (index < 0 || index >= (2*NUM_ARITH_TBLS))
  225.       ERREXIT1(cinfo->emethods, "Bogus DAC index %d", index);
  226.  
  227.     if (index >= NUM_ARITH_TBLS) { /* define AC table */
  228.       cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = val;
  229.     } else {            /* define DC table */
  230.       cinfo->arith_dc_L[index] = val & 0x0F;
  231.       cinfo->arith_dc_U[index] = val >> 4;
  232.       if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
  233.     ERREXIT1(cinfo->emethods, "Bogus DAC value 0x%x", val);
  234.     }
  235.  
  236.     length -= 2;
  237.   }
  238. }
  239.  
  240.  
  241. LOCAL void
  242. get_dqt (decompress_info_ptr cinfo)
  243. /* Process a DQT marker */
  244. {
  245.   INT32 length;
  246.   int n, i, prec;
  247.   UINT16 tmp;
  248.   QUANT_TBL_PTR quant_ptr;
  249.   
  250.   length = get_2bytes(cinfo) - 2;
  251.   
  252.   while (length > 0) {
  253.     n = JGETC(cinfo);
  254.     prec = n >> 4;
  255.     n &= 0x0F;
  256.  
  257.     TRACEMS2(cinfo->emethods, 1,
  258.          "Define Quantization Table %d  precision %d", n, prec);
  259.  
  260.     if (n >= NUM_QUANT_TBLS)
  261.       ERREXIT1(cinfo->emethods, "Bogus table number %d", n);
  262.       
  263.     if (cinfo->quant_tbl_ptrs[n] == NULL)
  264.       cinfo->quant_tbl_ptrs[n] = (*cinfo->emethods->alloc_small) (SIZEOF(QUANT_TBL));
  265.     quant_ptr = cinfo->quant_tbl_ptrs[n];
  266.  
  267.     for (i = 0; i < DCTSIZE2; i++) {
  268.       tmp = JGETC(cinfo);
  269.       if (prec)
  270.     tmp = (tmp<<8) + JGETC(cinfo);
  271.       quant_ptr[i] = tmp;
  272.     }
  273.  
  274.     for (i = 0; i < DCTSIZE2; i += 8) {
  275.       TRACEMS8(cinfo->emethods, 2, "        %4d %4d %4d %4d %4d %4d %4d %4d",
  276.            quant_ptr[i  ], quant_ptr[i+1], quant_ptr[i+2], quant_ptr[i+3],
  277.            quant_ptr[i+4], quant_ptr[i+5], quant_ptr[i+6], quant_ptr[i+7]);
  278.     }
  279.  
  280.     length -= DCTSIZE2+1;
  281.     if (prec) length -= DCTSIZE2;
  282.   }
  283. }
  284.  
  285.  
  286. LOCAL void
  287. get_dri (decompress_info_ptr cinfo)
  288. /* Process a DRI marker */
  289. {
  290.   if (get_2bytes(cinfo) != 4)
  291.     ERREXIT(cinfo->emethods, "Bogus length in DRI");
  292.  
  293.   cinfo->restart_interval = get_2bytes(cinfo);
  294.  
  295.   TRACEMS1(cinfo->emethods, 1,
  296.        "Define Restart Interval %d", cinfo->restart_interval);
  297. }
  298.  
  299.  
  300. LOCAL void
  301. get_app0 (decompress_info_ptr cinfo)
  302. /* Process an APP0 marker */
  303. {
  304. #define JFIF_LEN 14
  305.   INT32 length;
  306.   UINT8 b[JFIF_LEN];
  307.   int buffp;
  308.  
  309.   length = get_2bytes(cinfo) - 2;
  310.  
  311.   /* See if a JFIF APP0 marker is present */
  312.  
  313.   if (length >= JFIF_LEN) {
  314.     for (buffp = 0; buffp < JFIF_LEN; buffp++)
  315.       b[buffp] = JGETC(cinfo);
  316.     length -= JFIF_LEN;
  317.  
  318.     if (b[0]=='J' && b[1]=='F' && b[2]=='I' && b[3]=='F' && b[4]==0) {
  319.       /* Found JFIF APP0 marker: check version */
  320.       /* Major version must be 1 */
  321.       if (b[5] != 1)
  322.     ERREXIT2(cinfo->emethods, "Unsupported JFIF revision number %d.%02d",
  323.          b[5], b[6]);
  324.       /* Minor version should be 0 or 1, but try to process anyway if newer */
  325.       if (b[6] != 0 && b[6] != 1)
  326.     TRACEMS2(cinfo->emethods, 0, "Warning: unknown JFIF revision number %d.%02d",
  327.          b[5], b[6]);
  328.       /* Save info */
  329.       cinfo->density_unit = b[7];
  330.       cinfo->X_density = (b[8] << 8) + b[9];
  331.       cinfo->Y_density = (b[10] << 8) + b[11];
  332.       /* Assume colorspace is YCbCr, unless UI has overridden me */
  333.       if (cinfo->jpeg_color_space == CS_UNKNOWN)
  334.     cinfo->jpeg_color_space = CS_YCbCr;
  335.       TRACEMS3(cinfo->emethods, 1, "JFIF APP0 marker, density %dx%d  %d",
  336.            cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
  337.     } else {
  338.       TRACEMS(cinfo->emethods, 1, "Unknown APP0 marker (not JFIF)");
  339.     }
  340.   } else {
  341.     TRACEMS1(cinfo->emethods, 1,
  342.          "Short APP0 marker, length %d", (int) length);
  343.   }
  344.  
  345.   while (length-- > 0)        /* skip any remaining data */
  346.     (void) JGETC(cinfo);
  347. }
  348.  
  349.  
  350. LOCAL void
  351. get_sof (decompress_info_ptr cinfo, int code)
  352. /* Process a SOFn marker */
  353. {
  354.   INT32 length;
  355.   short ci;
  356.   int c;
  357.   jpeg_component_info * compptr;
  358.   
  359.   length = get_2bytes(cinfo);
  360.   
  361.   cinfo->data_precision = JGETC(cinfo);
  362.   cinfo->image_height   = get_2bytes(cinfo);
  363.   cinfo->image_width    = get_2bytes(cinfo);
  364.   cinfo->num_components = JGETC(cinfo);
  365.  
  366.   TRACEMS4(cinfo->emethods, 1,
  367.        "Start Of Frame 0x%02x: width=%d, height=%d, components=%d",
  368.        code, cinfo->image_width, cinfo->image_height,
  369.        cinfo->num_components);
  370.  
  371.   /* We don't support files in which the image height is initially specified */
  372.   /* as 0 and is later redefined by DNL.  As long as we have to check that,  */
  373.   /* might as well have a general sanity check. */
  374.   if (cinfo->image_height <= 0 || cinfo->image_width <= 0
  375.       || cinfo->num_components <= 0)
  376.     ERREXIT(cinfo->emethods, "Empty JPEG image (DNL not supported)");
  377.  
  378. #ifdef EIGHT_BIT_SAMPLES
  379.   if (cinfo->data_precision != 8)
  380.     ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
  381. #endif
  382. #ifdef TWELVE_BIT_SAMPLES
  383.   if (cinfo->data_precision != 12) /* this needs more thought?? */
  384.     ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
  385. #endif
  386. #ifdef SIXTEEN_BIT_SAMPLES
  387.   if (cinfo->data_precision != 16) /* this needs more thought?? */
  388.     ERREXIT(cinfo->emethods, "Unsupported JPEG data precision");
  389. #endif
  390.  
  391.   if (length != (cinfo->num_components * 3 + 8))
  392.     ERREXIT(cinfo->emethods, "Bogus SOF length");
  393.  
  394.   cinfo->comp_info = (*cinfo->emethods->alloc_small)
  395.             (cinfo->num_components * SIZEOF(jpeg_component_info));
  396.   
  397.   for (ci = 0; ci < cinfo->num_components; ci++) {
  398.     compptr = &cinfo->comp_info[ci];
  399.     compptr->component_index = ci;
  400.     compptr->component_id = JGETC(cinfo);
  401.     c = JGETC(cinfo);
  402.     compptr->h_samp_factor = (c >> 4) & 15;
  403.     compptr->v_samp_factor = (c     ) & 15;
  404.     compptr->quant_tbl_no  = JGETC(cinfo);
  405.       
  406.     TRACEMS4(cinfo->emethods, 1, "    Component %d: %dhx%dv q=%d",
  407.          compptr->component_id, compptr->h_samp_factor,
  408.          compptr->v_samp_factor, compptr->quant_tbl_no);
  409.   }
  410. }
  411.  
  412.  
  413. LOCAL void
  414. get_sos (decompress_info_ptr cinfo)
  415. /* Process a SOS marker */
  416. {
  417.   INT32 length;
  418.   int i, ci, n, c, cc;
  419.   jpeg_component_info * compptr;
  420.   
  421.   length = get_2bytes(cinfo);
  422.   
  423.   n = JGETC(cinfo);  /* Number of components */
  424.   cinfo->comps_in_scan = n;
  425.   length -= 3;
  426.   
  427.   if (length != (n * 2 + 3) || n < 1 || n > MAX_COMPS_IN_SCAN)
  428.     ERREXIT(cinfo->emethods, "Bogus SOS length");
  429.  
  430.   TRACEMS1(cinfo->emethods, 1, "Start Of Scan: %d components", n);
  431.   
  432.   for (i = 0; i < n; i++) {
  433.     cc = JGETC(cinfo);
  434.     c = JGETC(cinfo);
  435.     length -= 2;
  436.     
  437.     for (ci = 0; ci < cinfo->num_components; ci++)
  438.       if (cc == cinfo->comp_info[ci].component_id)
  439.     break;
  440.     
  441.     if (ci >= cinfo->num_components)
  442.       ERREXIT(cinfo->emethods, "Invalid component number in SOS");
  443.     
  444.     compptr = &cinfo->comp_info[ci];
  445.     cinfo->cur_comp_info[i] = compptr;
  446.     compptr->dc_tbl_no = (c >> 4) & 15;
  447.     compptr->ac_tbl_no = (c     ) & 15;
  448.     
  449.     TRACEMS3(cinfo->emethods, 1, "    c%d: [dc=%d ac=%d]", cc,
  450.          compptr->dc_tbl_no, compptr->ac_tbl_no);
  451.   }
  452.   
  453.   while (length > 0) {
  454.     (void) JGETC(cinfo);
  455.     length--;
  456.   }
  457. }
  458.  
  459.  
  460. LOCAL void
  461. get_soi (decompress_info_ptr cinfo)
  462. /* Process an SOI marker */
  463. {
  464.   int i;
  465.   
  466.   TRACEMS(cinfo->emethods, 1, "Start of Image");
  467.  
  468.   /* Reset all parameters that are defined to be reset by SOI */
  469.  
  470.   for (i = 0; i < NUM_ARITH_TBLS; i++) {
  471.     cinfo->arith_dc_L[i] = 0;
  472.     cinfo->arith_dc_U[i] = 1;
  473.     cinfo->arith_ac_K[i] = 5;
  474.   }
  475.   cinfo->restart_interval = 0;
  476.  
  477.   cinfo->density_unit = 0;    /* set default JFIF APP0 values */
  478.   cinfo->X_density = 1;
  479.   cinfo->Y_density = 1;
  480.  
  481.   cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling */
  482. }
  483.  
  484.  
  485. LOCAL int
  486. next_marker (decompress_info_ptr cinfo)
  487. /* Find the next JPEG marker */
  488. /* Note that the output might not be a valid marker code, */
  489. /* but it will never be 0 or FF */
  490. {
  491.   int c, nbytes;
  492.  
  493.   nbytes = 0;
  494.   do {
  495.     do {            /* skip any non-FF bytes */
  496.       nbytes++;
  497.       c = JGETC(cinfo);
  498.     } while (c != 0xFF);
  499.     do {            /* skip any duplicate FFs */
  500.       nbytes++;
  501.       c = JGETC(cinfo);
  502.     } while (c == 0xFF);
  503.   } while (c == 0);        /* repeat if it was a stuffed FF/00 */
  504.  
  505.   if (nbytes != 2)
  506.     TRACEMS2(cinfo->emethods, 1, "Skipped %d bytes before marker 0x%02x",
  507.          nbytes-2, c);
  508.  
  509.   return c;
  510. }
  511.  
  512.  
  513. LOCAL JPEG_MARKER
  514. process_tables (decompress_info_ptr cinfo)
  515. /* Scan and process JPEG markers that can appear in any order */
  516. /* Return when an SOI, EOI, SOFn, or SOS is found */
  517. {
  518.   int c;
  519.  
  520.   while (TRUE) {
  521.     c = next_marker(cinfo);
  522.       
  523.     switch (c) {
  524.     case M_SOF0:
  525.     case M_SOF1:
  526.     case M_SOF2:
  527.     case M_SOF3:
  528.     case M_SOF5:
  529.     case M_SOF6:
  530.     case M_SOF7:
  531.     case M_JPG:
  532.     case M_SOF9:
  533.     case M_SOF10:
  534.     case M_SOF11:
  535.     case M_SOF13:
  536.     case M_SOF14:
  537.     case M_SOF15:
  538.     case M_SOI:
  539.     case M_EOI:
  540.     case M_SOS:
  541.       return c;
  542.       
  543.     case M_DHT:
  544.       get_dht(cinfo);
  545.       break;
  546.       
  547.     case M_DAC:
  548.       get_dac(cinfo);
  549.       break;
  550.       
  551.     case M_DQT:
  552.       get_dqt(cinfo);
  553.       break;
  554.       
  555.     case M_DRI:
  556.       get_dri(cinfo);
  557.       break;
  558.       
  559.     case M_APP0:
  560.       get_app0(cinfo);
  561.       break;
  562.  
  563.     case M_RST0:        /* these are all parameterless */
  564.     case M_RST1:
  565.     case M_RST2:
  566.     case M_RST3:
  567.     case M_RST4:
  568.     case M_RST5:
  569.     case M_RST6:
  570.     case M_RST7:
  571.     case M_TEM:
  572.       TRACEMS1(cinfo->emethods, 1, "Unexpected marker 0x%02x", c);
  573.       break;
  574.  
  575.     default:    /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
  576.       skip_variable(cinfo, c);
  577.       break;
  578.     }
  579.   }
  580. }
  581.  
  582.  
  583.  
  584. /*
  585.  * Initialize and read the file header (everything through the SOF marker).
  586.  */
  587.  
  588. METHODDEF void
  589. read_file_header (decompress_info_ptr cinfo)
  590. {
  591.   int c;
  592.  
  593.   /* Expect an SOI marker first */
  594.   if (next_marker(cinfo) == M_SOI)
  595.     get_soi(cinfo);
  596.   else
  597.     ERREXIT(cinfo->emethods, "File does not start with JPEG SOI marker");
  598.  
  599.   /* Process markers until SOF */
  600.   c = process_tables(cinfo);
  601.  
  602.   switch (c) {
  603.   case M_SOF0:
  604.   case M_SOF1:
  605.     get_sof(cinfo, c);
  606.     cinfo->arith_code = FALSE;
  607.     break;
  608.       
  609.   case M_SOF9:
  610.     get_sof(cinfo, c);
  611.     cinfo->arith_code = TRUE;
  612.     break;
  613.  
  614.   default:
  615.     ERREXIT1(cinfo->emethods, "Unsupported SOF marker type 0x%02x", c);
  616.     break;
  617.   }
  618.  
  619.   /* Figure out what colorspace we have */
  620.   /* (too bad the JPEG committee didn't provide a real way to specify this) */
  621.  
  622.   switch (cinfo->num_components) {
  623.   case 1:
  624.     cinfo->jpeg_color_space = CS_GRAYSCALE;
  625.     break;
  626.  
  627.   case 3:
  628.     /* if we saw a JFIF marker, leave it set to YCbCr; */
  629.     /* also leave it alone if UI has provided a value */
  630.     if (cinfo->jpeg_color_space == CS_UNKNOWN) {
  631.       short cid0 = cinfo->comp_info[0].component_id;
  632.       short cid1 = cinfo->comp_info[1].component_id;
  633.       short cid2 = cinfo->comp_info[2].component_id;
  634.  
  635.       if (cid0 == 1 && cid1 == 2 && cid2 == 3)
  636.     cinfo->jpeg_color_space = CS_YCbCr; /* assume it's JFIF w/out marker */
  637.       else if (cid0 == 1 && cid1 == 4 && cid2 == 5)
  638.     cinfo->jpeg_color_space = CS_YIQ; /* prototype's YIQ matrix */
  639.       else {
  640.     TRACEMS3(cinfo->emethods, 0,
  641.          "Unrecognized component IDs %d %d %d, assuming YCbCr",
  642.          cid0, cid1, cid2);
  643.     cinfo->jpeg_color_space = CS_YCbCr;
  644.       }
  645.     }
  646.     break;
  647.  
  648.   case 4:
  649.     cinfo->jpeg_color_space = CS_CMYK;
  650.     break;
  651.  
  652.   default:
  653.     cinfo->jpeg_color_space = CS_UNKNOWN;
  654.     break;
  655.   }
  656. }
  657.  
  658.  
  659. /*
  660.  * Read the start of a scan (everything through the SOS marker).
  661.  * Return TRUE if find SOS, FALSE if find EOI.
  662.  */
  663.  
  664. METHODDEF boolean
  665. read_scan_header (decompress_info_ptr cinfo)
  666. {
  667.   int c;
  668.   
  669.   /* Process markers until SOS or EOI */
  670.   c = process_tables(cinfo);
  671.   
  672.   switch (c) {
  673.   case M_SOS:
  674.     get_sos(cinfo);
  675.     return TRUE;
  676.     
  677.   case M_EOI:
  678.     TRACEMS(cinfo->emethods, 1, "End Of Image");
  679.     return FALSE;
  680.  
  681.   default:
  682.     ERREXIT1(cinfo->emethods, "Unexpected marker 0x%02x", c);
  683.     break;
  684.   }
  685.   return FALSE;            /* keeps lint happy */
  686. }
  687.  
  688.  
  689. /*
  690.  * Finish up after a compressed scan (series of read_jpeg_data calls);
  691.  * prepare for another read_scan_header call.
  692.  */
  693.  
  694. METHODDEF void
  695. read_scan_trailer (decompress_info_ptr cinfo)
  696. {
  697.   /* no work needed */
  698. }
  699.  
  700.  
  701. /*
  702.  * Finish up at the end of the file.
  703.  */
  704.  
  705. METHODDEF void
  706. read_file_trailer (decompress_info_ptr cinfo)
  707. {
  708.   /* no work needed */
  709. }
  710.  
  711.  
  712. /*
  713.  * The method selection routine for standard JPEG header reading.
  714.  * Note that this must be called by the user interface before calling
  715.  * jpeg_decompress.  When a non-JFIF file is to be decompressed (TIFF,
  716.  * perhaps), the user interface must discover the file type and call
  717.  * the appropriate method selection routine.
  718.  */
  719.  
  720. GLOBAL void
  721. jselrjfif (decompress_info_ptr cinfo)
  722. {
  723.   cinfo->methods->read_file_header = read_file_header;
  724.   cinfo->methods->read_scan_header = read_scan_header;
  725.   /* For JFIF/raw-JPEG format, the user interface supplies read_jpeg_data. */
  726. #if 0
  727.   cinfo->methods->read_jpeg_data = read_jpeg_data;
  728. #endif
  729.   cinfo->methods->read_scan_trailer = read_scan_trailer;
  730.   cinfo->methods->read_file_trailer = read_file_trailer;
  731. }
  732.  
  733. #endif /* JFIF_SUPPORTED */
  734.